public class ChromoGray extends Chromo
{
	public String label;

	public static int BITS = 31; // allocate 1-bit for sign

	/*******************************************************************************
	 * INSTANCE VARIABLES *
	 *******************************************************************************/

	private static double randnum;

	public ChromoGray()
	{
		label = "Chromo Gray"; // for debug
		BITS = Parameters.geneSize - 1; // allocate 1-bit for sign

		char geneBit;
		chromo = "";
		for (int i = 0; i < Parameters.numGenes; i++) {
			for (int j = 0; j < Parameters.geneSize; j++) {
				randnum = Search.r.nextDouble();
				if (randnum > 0.5)
					geneBit = '0';
				else
					geneBit = '1';
				this.chromo = chromo + geneBit;
			}
		}
	}

	
	@Override
	public int getIntGeneValue(int geneID)
	{
		String geneAlpha = "";
		int geneValue;
		int grayGeneValue; // for debug

		char geneSign;
		char geneBit;
		geneValue = 0;
		grayGeneValue = 0;

		geneAlpha = getGeneAlpha(geneID);
		for (int i = Parameters.geneSize - 1; i >= 1; i--) {
			geneBit = geneAlpha.charAt(i);
			if (geneBit == '1')
				grayGeneValue = grayGeneValue
						+ (int) Math.pow(2.0, Parameters.geneSize - i - 1);
		}

		geneValue = gray_to_binary(grayGeneValue);

		geneSign = geneAlpha.charAt(0);
		if (geneSign == '1')
			geneValue = geneValue
					- (int) Math.pow(2.0, Parameters.geneSize - 1);

		return (geneValue);
	}

	// Get Integer Value of a Gene (Positive only) ****************************
	@Override
	public int getPosIntGeneValue(int geneID)
	{
		String geneAlpha = "";
		int geneValue;
		int grayGeneValue;

		char geneBit;
		geneValue = 0;
		grayGeneValue = 0;

		geneAlpha = getGeneAlpha(geneID);
		for (int i = Parameters.geneSize - 1; i >= 0; i--) {
			geneBit = geneAlpha.charAt(i);
			if (geneBit == '1')
				grayGeneValue = grayGeneValue
						+ (int) Math.pow(2.0, Parameters.geneSize - i - 1);
		}

		geneValue = gray_to_binary(grayGeneValue);

		return (geneValue);
	}
	
	public static final int binary_to_gray(final int p_data)
	{
		int l_i, l_shift;
		boolean l_b, l_c;

		l_shift = (1 << (BITS - 1));
		l_b = ((p_data & l_shift) != 0);
		l_i = (l_b ? l_shift : 0);

		do {
			l_shift >>>= 1;
			l_c = ((p_data & l_shift) != 0);
			if (l_b ^ l_c) {
				l_i |= l_shift;
			}

			l_b = l_c;
		} while (l_shift != 1);

		// System.out.println(l_i);

		return l_i;
	}

	public static final int gray_to_binary(final int p_data)
	{
		int l_i, l_shift;
		boolean l_b;

		l_shift = (1 << (BITS - 1));
		l_b = ((p_data & l_shift) != 0);
		l_i = (l_b ? l_shift : 0);

		do {
			l_shift >>>= 1;

			l_b ^= ((p_data & l_shift) != 0);
			if (l_b) {
				l_i |= l_shift;
			}

		} while (l_shift != 1);

		// System.out.println(l_i);

		return l_i;
	}


	// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public void test(String[] args) throws java.io.IOException
	{
		// Read Parameter File
		System.out.println("\nParameter File Name is: " + args[0] + "\n");
		Parameters parmValues = new Parameters(args[0]);

		int test = 0, graytest = 8;
		String grayPrint = Integer.toBinaryString(graytest);
		System.out.println("Gray: " + grayPrint);

		test = gray_to_binary(graytest);
		System.out.println("Int value of Gray Code: " + test);

		String binPrint = Integer.toBinaryString(test);
		System.out.println("Binary: " + binPrint);
	}

	private void yarg(String prefix, int n) // for debug only
	{
		if (n == 0)
			System.out.println(prefix);
		else {
			gray(prefix + "1", n - 1);
			yarg(prefix + "0", n - 1);
		}
	}

	private void gray(String prefix, int n) // for debug only
	{
		if (n == 0)
			System.out.println(prefix);
		else {
			gray(prefix + "0", n - 1);
			yarg(prefix + "1", n - 1);
		}
	}

	// public static void main(String[] args) throws java.io.IOException
	// {
	// Chromo test1 = new ChromoGray();
	// ((ChromoGray) test1).test(args);
	// }

}